<?php

///////////////////////////////////////////////////////////////////////////////
/*
database_manager.php

Class DatabaseManager:
Singleton class to manage MySQL database connection, perform queries, and trap
fatal database errors (e.g. erroneous sql statements).

Usage:  Script using this class should do the following:

require("config.inc.php");
require("database_manager.php");

// Connect when ready to use database:
DatabaseManager::getInstance(DB_SERVER, DB_USER, DB_PASS, DB_DATABASE)->connect();

// Execute SQL statements:
$result = DatabaseManager::getInstance()->query("sql command here")

// Disconnect when database no longer needed:
DatabaseManager::getInstance()->disconnect();


Since this is based on the Singleton design, do not directly instantiate this class.

config.inc.php contents (required in a php script):

< ? php (remove spaces)
    define('DB_SERVER', "database_server");
    define('DB_USER', "database_user_name");
    define('DB_PASS', "database_password");
    define('DB_DATABASE', "database_name");
? > (remove space)
 

TODO list:
- improve error condition checking and handling

*/
///////////////////////////////////////////////////////////////////////////////

class DatabaseManager {

    // Store the single instance of DatabaseManager
    private static $instance;
    
    private $databaseConnection;
    private $errno;
    private $error;

    private $databaseHost;
    private $databaseUser;
    private $databasePassword;
    private $databaseName;

    /////////////////////////////////////////////////////////////////////////////
    private function __construct($databaseHost=null, $databaseUser=null,
                                 $databasePassword=null, $databaseName=null){
        error_reporting(E_ALL);
        // error catching if not passed in
        if($databaseHost==null || $databaseUser==null || $databaseName==null){
            $this->error("Database information must be passed in when the object is first created.");
        }
        $this->databaseHost=$databaseHost;
        $this->databaseUser=$databaseUser;
        $this->databasePassword=$databasePassword;
        $this->databaseName=$databaseName; 
    }

    /////////////////////////////////////////////////////////////////////////////
    public function connect() {
        error_reporting(E_ALL);
        $this->databaseConnection = new mysqli($this->databaseHost, $this->databaseUser,
                                               $this->databasePassword, $this->databaseName);
        if (mysqli_connect_errno()) {
            $this->error("Connect failed: %s\n", mysqli_connect_error());
        }
        // not sure why this was originally put here
        //$stmt =  $this->databaseConnection->stmt_init();
        $this->clearCredentials();

    }

    /////////////////////////////////////////////////////////////////////////////
    public function disconnect() {
        $this->databaseConnection->close();
    }

    /////////////////////////////////////////////////////////////////////////////
    public function query($sql) {
        $result = $this->getDatabaseConnection()->query($sql);
        if (!$result) {
            $this->setErrno($this->getDatabaseConnection()->errno);
            $this->setError($this->getDatabaseConnection()->error);

            die("Database Error " . $this->getErrno() . " : " .
                                    $this->getError() . "\nSQL: " . $sql . "\n");
        }
        return $result;
    }

    /////////////////////////////////////////////////////////////////////////////
    public static function getInstance($databaseHost=null, $databaseUser=null,
                                       $databasePassword=null, $databaseName=null){
        if (!self::$instance){
            $className = __CLASS__;
            self::$instance = new $className($databaseHost, $databaseUser,
                                             $databasePassword, $databaseName);
        }
        return self::$instance;
    }

    /////////////////////////////////////////////////////////////////////////////
    public function getDatabaseConnection() {
        return $this->databaseConnection;
    }

    /////////////////////////////////////////////////////////////////////////////
    private function clearCredentials() {
        // No sense in keeping this data in memory.
        $this->databaseHost="";
        $this->databaseUser="";
        $this->databasePassword="";
        $this->databaseName=""; 
    }

    /////////////////////////////////////////////////////////////////////////////
    public function getError() {
        return $this->error;
    }
    /////////////////////////////////////////////////////////////////////////////
    private function setError($error) {
        $this->error = $error;
    }
    /////////////////////////////////////////////////////////////////////////////
    public function getErrno() {
        return $this->errno;
    }
    /////////////////////////////////////////////////////////////////////////////
    private function setErrno($errno) {
        $this->errno = $errno;
    }

    /////////////////////////////////////////////////////////////////////////////
    private function error($message='') {
        print("Database Error: " . $message . "\n");
        exit();  // May decide on better/cleaner action.
    }



}

?>
